package com.basic.business.order.server;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.RateLimiter;
import com.basic.business.common.constants.KmConstants;
import com.basic.business.common.utils.DateUtils;
import com.basic.business.common.utils.kmUtil.PostParamsUtil;
import com.basic.business.common.utils.SpringUtils;
import com.basic.business.order.domain.TOrdersMain;
import com.basic.business.order.service.ITOrdersMainService;
import com.basic.business.packaging.server.AutomaticPackagingServer;
import com.basic.business.redis.server.SyncOrdersToRedisServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * 获取订单数据
 *
 * @author zhaoxy_jn@163.com
 */
@Slf4j
@Component
public class GetOrdersDataServer {

    // 默认时间范围
    public static String[] DEFAULT_TIME_RANGE = new String[]{"2025-04-15 17:00:00", "2025-04-15 17:00:59"};

    private ScheduledFuture<?> scheduledTask;

    // 定义限流器，每秒最多处理 0.5 个请求 快麦平台一分钟最多请求60次，官方技术人员建议不超过30次
    private static final RateLimiter rateLimiter = RateLimiter.create(0.5);

    private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

    @Resource
    private ITOrdersMainService mainService;

    /**
     * 前置任务
     * 1. 获取存储的最后一条订单记录的时间戳，作为本次请求的开始时间戳
     */
    public void predecessors() {
        // 获取存储的最后更新时间
        Long lastUpdTime = mainService.getLastUpdTime();
        // 如果lastUpdTime不为空，则删除当前时间戳下的记录
        if (lastUpdTime != null) {
            Long zeroTimestamp = DateUtils.getZeroTimestamp(lastUpdTime);
            int delCnt = mainService.delByUpdTime(zeroTimestamp);
            log.warn("初始化程序，删除时间{}之后的数据{}条", DateUtils.timestampToDate(zeroTimestamp), delCnt);
            // 计算新的时间范围
            DEFAULT_TIME_RANGE = DateUtils.getOneMinuteTimeRange(lastUpdTime);
        }

        // 默认设置999999999小时轮询一次，防止初始化时间和当前时间差过大导致任务重复执行
        startTask(0, 999999999, DEFAULT_TIME_RANGE, TimeUnit.HOURS);

    }

    /**
     * 启动任务
     * @param initialDelay 初始执行时间 0立即执行
     * @param delay 执行间隔
     * @param timeRange 时间范围
     * @param unit 时间单位
     */
    private void startTask(long initialDelay, long delay,String[] timeRange,TimeUnit unit){
        Runnable task = () -> getOrdersByUpdTime(timeRange, "1");
        scheduledTask = executor.scheduleAtFixedRate(task, initialDelay, delay, unit);
    }

    /**
     * 修改任务执行间隔
     * @param delay 新的间隔时间
     * @param timeRange 时间范围
     */
    private void changeDelay(long delay,String[] timeRange) {
        if (scheduledTask != null) {
            scheduledTask.cancel(false);
        }
        startTask(delay <= 0 ? 61000 : delay, 61000,timeRange,TimeUnit.MILLISECONDS);
    }

    /**
     * 获取订单数据
     */
    private void getOrdersByUpdTime(String[] timeRange, String pageNo) {
        try {
            // 判断当前时间是否大于 timeRange[1]，大于则继续处理，否则跳过
            if (!DateUtils.isBeforeNow(DateUtils.dateToTimestamp(timeRange[1]))) {
                // 计算下一分钟和当前时间的间差
                long diff = Long.parseLong(DateUtils.dateToTimestamp(timeRange[1])) - System.currentTimeMillis();
                changeDelay(diff, timeRange);
                return;
            }

            // 请求一个许可证，如果没有立即可用的许可证，这里会等待
            rateLimiter.acquire();

            // 构建业务参数
            Map<String, String> businessParams = Maps.newHashMap();
            businessParams.put("startTime", timeRange[0]);
            businessParams.put("endTime", timeRange[1]);
            String result = HttpUtil.post(KmConstants.URL, JSON.toJSONString(PostParamsUtil.getBusinessParams(pageNo, KmConstants.QUERY_OUTSTOCK_SIMPLE_METHOD, businessParams)));
            JSONObject jsonResult = JSONObject.parseObject(result);
            if (jsonResult.getBoolean("success")) {
                // 解析返回结果
                List<TOrdersMain> ordersMains = SpringUtils.getBean(ParseOrders.class).parseOrders(timeRange, jsonResult);
                if (!ordersMains.isEmpty()) {
                    // 保存数据库
                    int cnt = mainService.batchInsertOrUpdate(ordersMains);
                    log.info("{}, 入库{}条", Arrays.toString(timeRange), cnt);
                    // 同步到Redis中
                    SyncOrdersToRedisServer.init(ordersMains);
                    // 自动处理
                    AutomaticPackagingServer.TimerInit(ordersMains);

                }

                boolean hasNext = jsonResult.getBoolean("hasNext");

                // hasNext 为 false 时，表示没有下一页
                if (!hasNext) {
                    pageNo = "1";
                    timeRange = DateUtils.getAfterOneMinuteRange(DateUtils.dateToTimestamp(timeRange[0]));
                }
                if (hasNext) {
                    pageNo = String.valueOf(Integer.parseInt(pageNo) + 1);
                }

                // 递归处理
                getOrdersByUpdTime(timeRange, pageNo);
            } else {
                log.error("API返回失败结果，{}", jsonResult.getString("msg"));
            }
        }catch (Exception e) {
            log.error("获取订单数据失败{}", e.toString());
        }
    }
}
